package org.urbansoft.icl.writer;

import java.io.*;
import java.util.Iterator;

import org.apache.log4j.Logger;
import org.urbansoft.iso.ISOUtil;
import org.urbansoft.icl.*;
import org.urbansoft.icl.record.*;
import org.urbansoft.icl.util.FileEncoding;
import org.urbansoft.icl.util.RecordLength;

/**
 * Graba archivos X9 con más 20000 cheques
 * 
 * @author Ricardo Reyes
 */
public class ICLXLFileWriter {

	private ICLFile iclFile;
	private File fileOut;
	// private ZipOutputStream oStream;
	private FileOutputStream oStream;
	private byte len[];
	private byte data[];
	private String texto;

	static Logger log = Logger.getLogger(ICLFileWriter.class);

	public ICLXLFileWriter(ICLFile iclFile, File fileOut) {
		this.iclFile = iclFile;
		this.fileOut = fileOut;
	}

	public void writeHeaderFile() throws IOException {
		// Soporte de zip
		// FileOutputStream normalFile = new FileOutputStream(fileOut);
		// oStream = new ZipOutputStream(normalFile);
		// oStream.putNextEntry(new
		// ZipEntry(fileOut.getName().substring(0,fileOut.getName().length()-4)));
		oStream = new FileOutputStream(fileOut);
		if (iclFile == null || fileOut == null) {
			return;
		} else {
			writeFileHeader();
			return;
		}
	}

	private void writeFileHeader() throws IOException {
		len = RecordLength.intToByteArray(iclFile.getFileHeader()
				.getRecordLength(), 4);
		data = iclFile.getFileHeader().getBytes();
		texto = iclFile.getFileHeader().toString();
		writeData();
		writeCashLetterHeader();
	}

	private void writeCashLetterHeader() throws IOException {
		for (Iterator it = iclFile.getCashLetterList().iterator(); it.hasNext(); writeData()) {
			CashLetter letter = (CashLetter) it.next();
			len = RecordLength.intToByteArray(letter.getCashLetterHeader()
					.getRecordLength(), 4);
			data = letter.getCashLetterHeader().getBytes();
			texto = letter.getCashLetterHeader().toString();
		}

	}

	public void writeBundleData(CashLetter letter,
			ForwardPresentmentBundle bundle) throws IOException {
		len = RecordLength.intToByteArray(bundle.getBundleHeader()
				.getRecordLength(), 4);
		data = bundle.getBundleHeader().getBytes();
		texto = bundle.getBundleHeader().toString();
		writeData();
		writeItemData(bundle);
		if (bundle.getBundleControl() != null) {
			len = RecordLength.intToByteArray(bundle.getBundleControl()
					.getRecordLength(), 4);
			data = bundle.getBundleControl().getBytes();
			texto = bundle.getBundleControl().toString();
			writeData();
		}
	}

	public void writeCashLetterControl(CashLetterControlRecord clcontrol)
			throws IOException {
		if (clcontrol != null) {
			len = RecordLength.intToByteArray(clcontrol.getRecordLength(), 4);
			data = clcontrol.getBytes();
			texto = clcontrol.toString();
			writeData();
		}
	}

	public void writeFileControl(FileControlRecord fcontrol) throws IOException {
		if (fcontrol != null) {
			len = RecordLength.intToByteArray(fcontrol.getRecordLength(), 4);
			data = fcontrol.getBytes();
			texto = fcontrol.toString();
			writeData();
		}
		// oStream.closeEntry(); //zip
		oStream.close();
	}

	private void writeItemData(ForwardPresentmentBundle bundle)
			throws IOException {

		String type = bundle.getBundleHeader().collectionTypeIndicator
				.getFieldData();
		if (type.equals("01")) {
			ICLItem item;
			for (Iterator it = bundle.getItemList().iterator(); it.hasNext(); writeImageData(item)) {
				item = (ICLItem) it.next();
				len = RecordLength.intToByteArray(item.getCheckDetail()
						.getRecordLength(), 4);
				data = item.getCheckDetail().getBytes();
				texto = item.getCheckDetail().toString();
				writeData();

				/* write any addendum A records */
				for (int i = 0; i < item.getCheckDetailAddendumAList().size(); i++) {
					len = RecordLength.intToByteArray(
							((CheckDetailAddendumARecord) item
									.getCheckDetailAddendumAList().get(i))
									.getRecordLength(), 4);
					data = ((CheckDetailAddendumARecord) item
							.getCheckDetailAddendumAList().get(i)).getBytes();
					texto = ((CheckDetailAddendumARecord) item
							.getCheckDetailAddendumAList().get(i)).toString();
					writeData();
				}

				/* write any addendum C records */
				for (int i = 0; i < item.getCheckDetailAddendumCList().size(); i++) {
					// log.info("EScribiendo addC:"+i);
					len = RecordLength.intToByteArray(item
							.getCheckDetailAddendumCList().get(i)
							.getRecordLength(), 4);
					data = item.getCheckDetailAddendumCList().get(i).getBytes();
					texto = item.getCheckDetailAddendumCList().get(i)
							.toString();
					writeData();
				}
			}

		} else {
			ReturnItem item;
			for (Iterator it = bundle.getItemList().iterator(); it.hasNext(); writeImageData(item)) {
				item = (ReturnItem) it.next();
				len = RecordLength.intToByteArray(item.getReturnDetail()
						.getRecordLength(), 4);
				data = item.getReturnDetail().getBytes();
				texto = item.getReturnDetail().toString();
				writeData();
				for (int i = 0; i < item.getReturnDetailAddendumAList().size(); i++) {
					len = RecordLength.intToByteArray(
							((ReturnAddendumARecord) item
									.getReturnDetailAddendumAList().get(i))
									.getRecordLength(), 4);
					data = ((ReturnAddendumARecord) item
							.getReturnDetailAddendumAList().get(i)).getBytes();
					texto = ((ReturnAddendumARecord) item
							.getReturnDetailAddendumAList().get(i)).toString();
					writeData();
				}

				if (item.getReturnAdd3501() != null) {
					len = RecordLength.intToByteArray(item.getReturnAdd3501()
							.getRecordLength(), 4);
					data = item.getReturnAdd3501().getBytes();
					texto = item.getReturnAdd3501().toString();
					writeData();
				}
				if (item.getReturnAdd3502() != null) {
					len = RecordLength.intToByteArray(item.getReturnAdd3502()
							.getRecordLength(), 4);
					data = item.getReturnAdd3502().getBytes();
					texto = item.getReturnAdd3502().toString();
					writeData();
				}
				if (item.getReturnAdd3503() != null) {
					len = RecordLength.intToByteArray(item.getReturnAdd3503()
							.getRecordLength(), 4);
					data = item.getReturnAdd3503().getBytes();
					texto = item.getReturnAdd3503().toString();
					writeData();
				}
				if (item.getReturnAdd3504() != null) {
					len = RecordLength.intToByteArray(item.getReturnAdd3504()
							.getRecordLength(), 4);
					data = item.getReturnAdd3504().getBytes();
					texto = item.getReturnAdd3504().toString();
					writeData();
				}
				if (item.getReturnAdd3505() != null) {
					len = RecordLength.intToByteArray(item.getReturnAdd3505()
							.getRecordLength(), 4);
					data = item.getReturnAdd3505().getBytes();
					texto = item.getReturnAdd3505().toString();
					writeData();
				}
				if (item.getReturnAdd3506() != null) {
					len = RecordLength.intToByteArray(item.getReturnAdd3506()
							.getRecordLength(), 4);
					data = item.getReturnAdd3506().getBytes();
					texto = item.getReturnAdd3506().toString();
					writeData();
				}
				for (int i = 0; i < item.getReturnDetailAddendumD3598List()
						.size(); i++) {
					len = RecordLength.intToByteArray(
							((ReturnAddendumD3598) item
									.getReturnDetailAddendumD3598List().get(i))
									.getRecordLength(), 4);
					data = ((ReturnAddendumD3598) item
							.getReturnDetailAddendumD3598List().get(i))
							.getBytes();
					texto = ((ReturnAddendumD3598) item
							.getReturnDetailAddendumD3598List().get(i))
							.toString();
					writeData();
				}

				for (int i = 0; i < item.getReturnDetailAddendumD3599List()
						.size(); i++) {
					len = RecordLength.intToByteArray(
							((ReturnAddendumD3599) item
									.getReturnDetailAddendumD3599List().get(i))
									.getRecordLength(), 4);
					data = ((ReturnAddendumD3599) item
							.getReturnDetailAddendumD3599List().get(i))
							.getBytes();
					texto = ((ReturnAddendumD3599) item
							.getReturnDetailAddendumD3599List().get(i))
							.toString();
					writeData();
				}
			}

		}
	}

	private void writeImageData(Item item) throws IOException {
		Iterator it = item.getImageViewList().iterator();
		do {
			if (!it.hasNext())
				break;
			ImageView view = (ImageView) it.next();
			if (view.getImageViewDetail() != null) {
				len = RecordLength.intToByteArray(view.getImageViewDetail()
						.getRecordLength(), 4);
				data = view.getImageViewDetail().getBytes();
				texto = view.getImageViewDetail().toString();
				writeData();
			}
			if (view.getImageViewData() != null) {
				len = RecordLength.intToByteArray(view.getImageViewData()
						.getRecordLength(), 4);
				data = view.getImageViewData().getBytes();
				texto = view.getImageViewData().toString();
				writeData();
			}
			if (view.getImageViewAnalysis() != null) {
				len = RecordLength.intToByteArray(view.getImageViewAnalysis()
						.getRecordLength(), 4);
				data = view.getImageViewAnalysis().getBytes();
				writeData();
			}
		} while (true);
	}

	private void writeData() throws IOException {
		if (oStream == null) {
			log.error("Output stream was null");
			throw new IOException("Output Stream is NULL");
		}
		oStream.write(len);
		if (iclFile.getFileEncoding() == FileEncoding.EBCDIC)
			data = ISOUtil.asciiToEbcdic(data);
		oStream.write(data);
	}

	public ICLFile getIclFile() {
		return iclFile;
	}

	public void setIclFile(ICLFile iclFile) {
		this.iclFile = iclFile;
	}

	public File getFileOut() {
		return fileOut;
	}

	public void setFileOut(File fileOut) {
		this.fileOut = fileOut;
	}

}